package edu.umassd.visual;

import java.awt.Color;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.stereotype.Component;

import edu.umassd.raddacl.Observation;
import edu.umassd.visual.util.Rectangle;

/**
 * The current data points showing on the screen.
 * 
 * @author Dan Avila
 * 
 */
@Component
public class DataPoints
{
	private Map<Color, List<Observation>> clusters = new ConcurrentHashMap<>();

	private volatile int xIndex = 0;
	private volatile int yIndex = 1;

	private volatile double[] min;
	private volatile double[] max;

	/**
	 * Add a new cluster to this point.
	 * 
	 * @param observations
	 *            - a collection of observation.
	 */
	public void addCluster(List<Observation> observations)
	{
		clusters.put(getColor(), observations);

		for (Observation obs : observations)
		{
			setMin(obs);
		}
	}

	private void setMin(Observation obs)
	{
		for (int i = 0; i < obs.size(); i++)
		{
			Double value = obs.get(i);

			if (min == null)
			{
				min = new double[obs.size()];
				Arrays.fill(min, Double.MAX_VALUE);
				max = new double[obs.size()];
				Arrays.fill(max, -Double.MAX_VALUE);
			}

			if (value > max[i])
			{
				max[i] = value;
			}

			if (value < min[i])
			{
				min[i] = value;
			}
		}
	}

	/**
	 * Gets an iterator that can be used to navigate over clusters.
	 * 
	 * @return the clusters to get.
	 */
	public Set<Entry<Color, List<Observation>>> clusters()
	{
		return clusters.entrySet();
	}

	private Color getColor()
	{
		Color c = new Color(getRGB(50, 205), getRGB(50, 205), getRGB(50, 205));

		return clusters.containsKey(c) ? getColor() : c;
	}

	private int getRGB(int min, int max)
	{
		return (int) (Math.random() * (max - min)) + min;
	}

	public Double getX(Observation obs)
	{
		return obs.get(xIndex);
	}

	public Double getY(Observation obs)
	{
		return obs.get(yIndex);
	}

	public void setXIndex(int xIndex)
	{
		this.xIndex = xIndex;
	}

	public void setYIndex(int yIndex)
	{
		this.yIndex = yIndex;
	}

	public Rectangle getBounds()
	{
		Rectangle rect = new Rectangle(0.0, 0.0);

		double x = min[xIndex];
		double y = min[yIndex];
		double width = max[xIndex] - x;
		double height = max[yIndex] - y;

		rect.setRect(x, y, width, height);

		return rect;
	}
}
